package exp;

import java.util.HashSet;

import def.AbstractText;
import def.Argument;
import def.BioNLPDocument;
import def.Event;

public class Evaluator {

	/**
	 * evaluate events for one line
	 * @param finalEvents
	 * @param doc
	 * @param lineno
	 * @param c
	 */
	public static void eval(HashSet<Event> finalEvents, BioNLPDocument doc, int lineno,
			Count c) {
		HashSet<String> truthString = new HashSet<String>(), predString = new HashSet<String>();
		AbstractText  text = (AbstractText)doc.text;
		for (Event e: doc.events.values()){
			if (text.getSentenceIdByPos(e.tspan.startIdx)!= lineno) continue;
			String str = e.tspan.getEvalString(doc)+",";
			for (Argument arg: e.args){
				String argStr = str + arg.tspan.getEvalString(doc);
				if (!truthString.contains(argStr)){
					truthString.add(argStr);
				}
			}
		}
		c.all+= truthString.size();
		HashSet<String> visited = new HashSet<String>();
		for (Event e:finalEvents){
			String str = e.tspan.startIdx+"-"+e.tspan.endIdx+",";
			for (Argument arg:e.args){
				String argStr = str+arg.tspan.startIdx+"-"+arg.tspan.endIdx;
				predString.add(argStr);
				String found = Evaluator.lookup(argStr, truthString);
				if (found==null){
					c.fp++;
				}
				else{
					if (!visited.contains(found)){
						c.num++;
						visited.add(found);
					}
				}
			}
		}
		System.err.println("[EVENT_ARGUMENT_STRING] "+truthString+" [PRED] "+predString);
	}

	/**
	 * 
	 * @param str
	 * @param set
	 * @return the string in truthset
	 */
	public static String lookup(String str, HashSet<String> set){
		String[] n = str.split("(,|\\-)");
		int[] m = new int[n.length];
		for (int i = 0; i < n.length; i++){
			m[i] = Integer.parseInt(n[i]);
		}
		for (String s: set){
			String[] items = s.split("(,|\\-)");
			int[] p = new int[items.length];
			for (int i = 0; i < n.length; i++){
				p[i] = Integer.parseInt(items[i]);
			}
			if (m[0] >= p[0] && m[1] <= p[1] && m[2] >= p[2] && m[3] <= p[3] ){
				return s;
			}
		}
		return null;
	}

	/**
	 * evaluate over a whole doc
	 * @param finalEvents
	 * @param doc
	 * @param c
	 */
	public static void eval2(HashSet<Event> finalEvents, BioNLPDocument doc,
			Count c) {
		int fp = finalEvents.size();
		HashSet<Event> tpInPred = new HashSet<Event>(), tpInTruth = new HashSet<Event>();
		HashSet<Event> truths = new HashSet<Event>();
		HashSet<String> truthString = new HashSet<String>();
		for (Event e: doc.events.values()){
			String str = e.toString();
			str = str.substring(str.indexOf("\t"));
			if (!truthString.contains(str)){
				truths.add(e);
				truthString.add(str);
			}
		}
		for (Event e:truths){
			c.all++;
			Event found = null;
			for (Event pe: finalEvents){
				//				if (tpInPred.contains(pe)) continue;
				if (pe.tspan.matchTruth(e.tspan, doc)){
					System.err.println("[EVAL TRUTH]"+e);
					System.err.println("[EVAL PRED]"+pe);
					// FIXME consider Site arguments TODO
					// NOTE: forget about the event types for now
					int match = 0;
					if (e.args.size() == pe.args.size()){
						for (int j = 0; j < e.args.size(); j++){
							for (int k = 0; k < pe.args.size(); k++){
								if (e.args.get(j).equals(pe.args.get(k)) && e.types.get(j) ==  pe.types.get(k)){
									match++;
								}
							}
						}
					}
					else{
						match = -1;
					}
					System.err.println("[EVAL EQUAL] "+(match ==  e.args.size())+" " +  match);
					if (match ==  e.args.size()){
						if (found!=null){
							System.err.println("already matched this "+e+" ---with--- "+found+"\n***but "+pe);
							break;
						}
						tpInPred.add(pe);
						tpInTruth.add(e);
						c.num ++;
						fp -- ;
						found =pe;
						//						break;
					}
				}
			}
		}
		c.fp += fp;
		System.out.println("=========================Predictions after post-processing:=========================");
		for (Event e: finalEvents){
			if (tpInPred.contains(e)){
				System.out.println(" +++++ "+e);	
			}
			else{
				System.out.println(" ***** "+e);
			}
		}
		System.out.println("=========================Truth:=========================");
		for (Event e: doc.events.values()){
			if (tpInTruth.contains(e)){
				System.out.println(" +++++ "+e);	
			}
			else{
				System.out.println(" ***** "+e);
			}
		}
		System.out.println(c);
	}

}
